
package mvcc

import (
	"context"

	"go.etcd.io/etcd/api/v3/mvccpb"
	"go.etcd.io/etcd/pkg/v3/traceutil"
	"go.etcd.io/etcd/server/v3/lease"
	"go.etcd.io/etcd/server/v3/storage/backend"
)

type RangeOptions struct {
	Limit int64	// 此次查询返回的键值对个数的上限。
	Rev   int64	// 扫描内存索引时使用到的mainrevision部分的值。
	Count bool	// 如果将该值设置为true，则只返回键值对个数，并不返回具体的键值对数据。
}

type RangeResult struct {
	KVs   []mvccpb.KeyValue	// 此次查询得到的键值对数据集合。
	Rev   int64
	Count int	// 此次查询返回的键值对个数。
}

// ReadView接口，该接口定义了只读事务相关的视图方法，
type ReadView interface {
	// FirstRev （）方法会返回开启当前只读事务时的revision信息，
	// 这与Rev（）方法相同，但是当进行一次压缩操作之后，
	// 该方法的返回佳会被更新成压缩时的revision信息，也就是压缩后的最小revision
	FirstRev() int64
	// Rev｛）方法会返回开启当前只读事务时的revision信息
	Rev() int64
	// 范围查询，
	Range(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error)
}

// TxnRead接口表示一个只读事务，其中内嵌了ReadView接口，
// 并在其基础上扩展了一个End（）方法，该End（）方法用来表示当前事务己经完成，并准备提交。
type TxnRead interface {
	ReadView
	// 结束标记事务已完成并准备提交。
	End()
}

// Write View接口中定义了读写事务相关的方法
type WriteView interface {
	// 范围删除，
	DeleteRange(key, end []byte) (n, rev int64)
	// 添加指定的键位对
	Put(key, value []byte, lease lease.LeaseID) (rev int64)
}

// TxnWrite接口表示一个读写事务，其中内嵌了TxnRead接口和WriteView接口，
// 井在两者的基础上扩展了一个Changes（）方法，该方法会返回自事务开启之后修改的键值对信息。
type TxnWrite interface {
	TxnRead
	WriteView
	// 更改获取自打开写入txn以来所做的更改。
	Changes() []mvccpb.KeyValue
}

// txnReadWrite强制将读取txn写入写操作，任何写操作都会导致恐慌。
type txnReadWrite struct{ TxnRead }

func (trw *txnReadWrite) DeleteRange(key, end []byte) (n, rev int64) { panic("unexpected DeleteRange") }
func (trw *txnReadWrite) Put(key, value []byte, lease lease.LeaseID) (rev int64) {
	panic("unexpected Put")
}
func (trw *txnReadWrite) Changes() []mvccpb.KeyValue { return nil }

func NewReadOnlyTxnWrite(txn TxnRead) TxnWrite { return &txnReadWrite{txn} }

type ReadTxMode uint32

const (
	// 使用ConcurrentReadTx并复制txReadBuffer 
	ConcurrentReadTxMode = ReadTxMode(1)
	// 使用后端ReadTx且未复制txReadBuffer 
	SharedBufReadTxMode = ReadTxMode(2)
)

type KV interface {
	ReadView	// 内嵌了ReadView接口和WriteView接口
	WriteView
	// 创建只读事务
	Read(mode ReadTxMode, trace *traceutil.Trace) TxnRead
	// 创建读写事务
	Write(trace *traceutil.Trace) TxnWrite
	// 哈希计算KV的后端。
	Hash() (hash uint32, revision int64, err error)
	// HashByRev计算给定版本之前所有MVCC版本的哈希值。
	HashByRev(rev int64) (hash uint32, revision int64, compactRev int64, err error)
	// 对整个KV存储进行压缩
	Compact(trace *traceutil.Trace, rev int64) (<-chan struct{}, error)
	// 提交事务
	Commit()
	// 从BoltDB中恢复内存索引
	Restore(b backend.Backend) error
	Close() error
}

// WatchableKV是可以监视的KV。
type WatchableKV interface {
	KV
	Watchable
}

// Watchable是包装NewWatchStream函数的接口。
type Watchable interface {
	// NewWatchStream返回一个可用于监视KV上发生的事件的监视流。
	// 
	NewWatchStream() WatchStream
}
